package procsim;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
 * Klasa za dijalog za pregled sadrzaja memorije
 */
public class MemoryDialog extends JDialog implements ActionListener, KeyListener {
    private JPanel panel = new JPanel(new BorderLayout());
    private JPanel panelSouth = new JPanel(new FlowLayout());
    private JTextArea ta = new JTextArea();
    private JScrollPane scroll = new JScrollPane(ta, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    private JButton buttonInsert = new JButton("Insert");
    private JButton buttonCancel = new JButton("Cancel");
    private JTextField tfAddress = new JTextField(4);
    private JTextField tfValue = new JTextField(4);
    private Memory memory;
    private Program parent;
    private String text;
    /**
     * Konstruktor - postavlja GUI elemente.
     * @param mem referenca na objekat memorije
     * @param prog referenca na glavni program, kako bi bio moguc pristup nekim njegovim metodama
     */
    MemoryDialog(Memory mem, Program prog){
        setTitle("Memory");
        memory = mem;
        parent = prog;
        update();
        ta.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 15));
        ta.setEditable(false);
        ta.setMargin(new Insets(3, 3, 3, 3));
        ta.addKeyListener(this);
        panelSouth.add(new JLabel("Address: ", SwingConstants.TRAILING));
        panelSouth.add(tfAddress);
        panelSouth.add(new JLabel("Value: ", SwingConstants.TRAILING));
        panelSouth.add(tfValue);
        panelSouth.add(buttonInsert);
        panelSouth.add(buttonCancel);
        buttonInsert.addActionListener(this);
        buttonInsert.addKeyListener(this);
        buttonCancel.addActionListener(this);
        buttonCancel.addKeyListener(this);
        tfAddress.addKeyListener(this);
        tfValue.addKeyListener(this);
        panel.add(scroll, "Center");
        panel.add(panelSouth, "South");
        setContentPane(panel);
        setSize(440, 350);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(HIDE_ON_CLOSE);
    }
    /**
     * Azurira tekstualni pregled memorije.
     */
    public void update(){
        text="";
        int nob = memory.numberOfBits();
        int now = memory.numberOfWords();
        int nowprint = (now>0x800) ? 0x800 : now;
        for(int i=0; i<nowprint; i++){
            if(i%8==0) text+=Util.int2HexForMemory(i, Math.getExponent(Util.roundToNextMultiple(now)))+": ";
            MSignal data=memory.readLightweight(i);
            int dataint;
            if(data==null) dataint=0;
            else dataint=data.get();
            text+=Util.int2HexForMemory(dataint, nob)+(i%8==7 ? ((i!=nowprint-1) ? "\n" : "") : " ");
        }
        ta.setText(text);
        ta.setCaretPosition(0);
    }
    /**
     * Obrada akcionih dogadjaja
     * @param e dogadjaj (pritisak na dugme)
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getActionCommand().equals("Insert")){
            String addr = tfAddress.getText();
            String val = tfValue.getText();
            try{
                memory.write(Util.hex2Int(addr, Math.getExponent(Util.roundToNextMultiple(memory.numberOfWords()))),
                             Util.hex2Int(val, memory.numberOfBits()));
                update();
                parent.setStatus("Mem["+addr+"] updated.");
            } catch(NumberFormatException nfe){
                JOptionPane.showMessageDialog(null, nfe.getLocalizedMessage(), "Input error", JOptionPane.ERROR_MESSAGE);
            }
        }
        else if(e.getActionCommand().equals("Cancel")){
            setVisible(false);
            tfAddress.setText("");
            tfValue.setText("");
        }
    }
    /**
     * Obrada dogadjaja kucanja na tastaturi. Ne radi nista.
     * @param ke dogadjaj
     */
    @Override
    public void keyTyped(KeyEvent ke) { }
    /**
     * Obrada dogadjaja kucanja na tastaturi.
     * @param ke dogadjaj
     */
    @Override
    public void keyPressed(KeyEvent ke) {
        if(ke.getKeyCode()==KeyEvent.VK_ESCAPE)
            setVisible(false);
        else if(ke.getKeyCode()==KeyEvent.VK_ENTER && (ke.getComponent() instanceof JButton || ke.getComponent() instanceof JTextField)){
            if(ke.getComponent()==buttonCancel)
                actionPerformed(new ActionEvent(ke.getComponent(), ActionEvent.ACTION_PERFORMED, buttonCancel.getText()));
            else
                actionPerformed(new ActionEvent(ke.getComponent(), ActionEvent.ACTION_PERFORMED, buttonInsert.getText()));
        }
    }
    /**
     * Obrada dogadjaja kucanja na tastaturi. Ne radi nista.
     * @param ke dogadjaj
     */
    @Override
    public void keyReleased(KeyEvent ke) { }
}
